/*
 * Curve2D.h
 *
 *  Created on: 2009/02/14
 *      Author: Yongshik Cho
 */

#ifndef CURVE2D_H_
#define CURVE2D_H_

#include <vector>
#include "Prerequisites.h"
#include "ISmartPtr.h"
#include "Vector2D.h"
#include "sqplus/sqplus.h"
using namespace SqPlus;


struct BezierNode
{
public:
	BezierNode(const Vector2D& pos, const float rot, const float w)
	{
		position = pos;
		rotation = rot;
		weight = w;
	}
	BezierNode(const BezierNode& rhs)
	{
		position = rhs.position;
		rotation = rhs.rotation;
		weight = rhs.weight;
	}

public:
	inline const BezierNode& operator = (const BezierNode& rhs)
	{
		position = rhs.position;
		rotation = rhs.rotation;
		weight = rhs.weight;

		return *this;
	}
	inline const bool operator == (const BezierNode& rhs)
	{
		return (position == rhs.position) && (rotation == rhs.rotation) && (weight == rhs.weight);
	}

public:
	Vector2D	position;
	float		rotation;
	float		weight;
	float		bezierLength;
	float		catmullLength;
};

class Curve2D : public ISmartPtr<Curve2D>
{
public:
	static const uint8 _LINEAR		= 0;
	static const uint8 _BEZIER		= 1;

public:
	static const uint32 _DEFAULT_STEP_COUNT			= 100;

public:
	Curve2D();
	virtual ~Curve2D();

private:
	const bool isExists(const BezierNode& node);

public:
	inline static const Vector2D getLinearBezierPoint(const Vector2D& p1, const Vector2D& p2, const float t)
	{
		return (1-t) * p1 + t * p2;
	}

	inline static const Vector2D getQuadraticBezierPoint(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3, const float t)
	{
		return (1-t) * (1-t) * p1 + 2.f * (1-t) * t * p2 + t * t * p3;
	}

	inline static const Vector2D getCubicBezierPoint(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3, const Vector2D& p4, const float t)
	{
		return (1-t) * (1-t) * (1-t) * p1 + 3.f * (1-t) * (1-t) * t * p2 + 3.f * (1-t) * t * t * p3 + t * t * t * p4;
	}

public:
	inline const uint32 getNodeCount() const { return (uint32)mNodes.size(); }
	void addNode(const BezierNode& node);
	void subNode(const BezierNode& node);

	BezierNode* getNode(const uint32 index);
	BezierNode* getNextNode();

	inline const bool getClosed() const { return mClosed; }
	inline void setClosed(const bool closed) { mClosed = closed; }

	inline const int32 getIndex() const { return mIndex; }
	void setIndex(const int32 index);

	inline const int8 getDirection() const { return mDirection; }
	void setDirection(const int8 dir);

	inline const uint8 getType() const { return mType; }
	inline void setType(const uint8 type) { mType = type; }

protected:
	vector<BezierNode*>		mNodes;
	int32					mIndex;
	bool					mClosed;
	int8					mDirection;
	uint8					mType;
};

//must be declared here
DECLARE_INSTANCE_TYPE(Curve2D)

#endif /* CURVE_H_ */
